using Microsoft.EntityFrameworkCore;
using SheLife.Domain.Entities;
using SheLife.Infrastructure.Data;

namespace SheLife.Infrastructure.Repositories
{
    /// <summary>
    /// 系统配置仓储实现
    /// </summary>
    public class SystemConfigRepository : Repository<SystemConfig>, ISystemConfigRepository
    {
        public SystemConfigRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<SystemConfig?> GetByKeyAsync(string key)
        {
            return await _dbSet.FirstOrDefaultAsync(c => c.Key == key);
        }

        public async Task<Dictionary<string, string>> GetByCategoryAsync(string category)
        {
            var configs = await _dbSet.Where(c => c.Category == category).ToListAsync();
            return configs.ToDictionary(c => c.Key, c => c.Value);
        }

        public async Task<Dictionary<string, string>> GetAllConfigsAsync()
        {
            var configs = await _dbSet.ToListAsync();
            return configs.ToDictionary(c => c.Key, c => c.Value);
        }

        public async Task<bool> UpdateConfigAsync(string key, string value)
        {
            var config = await _dbSet.FirstOrDefaultAsync(c => c.Key == key);
            if (config == null)
            {
                config = new SystemConfig { Key = key, Value = value };
                _dbSet.Add(config);
            }
            else
            {
                config.Value = value;
                config.UpdatedAt = DateTime.UtcNow;
            }

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> UpdateConfigsAsync(Dictionary<string, string> configs)
        {
            foreach (var kvp in configs)
            {
                var config = await _dbSet.FirstOrDefaultAsync(c => c.Key == kvp.Key);
                if (config == null)
                {
                    config = new SystemConfig { Key = kvp.Key, Value = kvp.Value };
                    _dbSet.Add(config);
                }
                else
                {
                    config.Value = kvp.Value;
                    config.UpdatedAt = DateTime.UtcNow;
                }
            }

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeleteConfigAsync(string key)
        {
            var config = await _dbSet.FirstOrDefaultAsync(c => c.Key == key);
            if (config != null)
            {
                _dbSet.Remove(config);
                await _context.SaveChangesAsync();
                return true;
            }

            return false;
        }

        public async Task<Dictionary<string, int>> GetConfigCountByCategoryAsync()
        {
            var configs = await _dbSet
                .GroupBy(c => c.Category)
                .Select(c => new { Category = c.Key, Count = c.Count() })
                .ToListAsync();

            return configs.ToDictionary(c => c.Category, c => c.Count);
        }
    }

    /// <summary>
    /// 用户设置仓储实现
    /// </summary>
    public class UserSettingRepository : Repository<UserSetting>, IUserSettingRepository
    {
        public UserSettingRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<UserSetting?> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId);
        }

        public async Task<Dictionary<string, string>> GetUserSettingsAsync(Guid userId)
        {
            var settings = await _dbSet.Where(s => s.UserId == userId).ToListAsync();
            return settings.ToDictionary(s => s.Key, s => s.Value);
        }

        public async Task<string?> GetUserSettingAsync(Guid userId, string key)
        {
            var setting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId && s.Key == key);
            return setting?.Value;
        }

        public async Task<bool> UpdateUserSettingAsync(Guid userId, string key, string value)
        {
            var setting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId && s.Key == key);
            if (setting == null)
            {
                setting = new UserSetting { UserId = userId, Key = key, Value = value };
                _dbSet.Add(setting);
            }
            else
            {
                setting.Value = value;
                setting.UpdatedAt = DateTime.UtcNow;
            }

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> UpdateUserSettingsAsync(Guid userId, Dictionary<string, string> settings)
        {
            foreach (var kvp in settings)
            {
                var setting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId && s.Key == kvp.Key);
                if (setting == null)
                {
                    setting = new UserSetting { UserId = userId, Key = kvp.Key, Value = kvp.Value };
                    _dbSet.Add(setting);
                }
                else
                {
                    setting.Value = kvp.Value;
                    setting.UpdatedAt = DateTime.UtcNow;
                }
            }

            await _context.SaveChangesAsync();
            return true;
        }

        public async Task<bool> DeleteUserSettingAsync(Guid userId, string key)
        {
            var setting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId && s.Key == key);
            if (setting != null)
            {
                _dbSet.Remove(setting);
                await _context.SaveChangesAsync();
                return true;
            }

            return false;
        }

        public async Task<Dictionary<string, int>> GetSettingCountByUsersAsync(IEnumerable<Guid> userIds)
        {
            var settings = await _dbSet
                .Where(s => userIds.Contains(s.UserId))
                .GroupBy(s => s.UserId)
                .Select(s => new { UserId = s.Key, Count = s.Count() })
                .ToListAsync();

            return settings.ToDictionary(s => s.UserId.ToString(), s => s.Count);
        }

        public async Task<Dictionary<string, int>> GetSettingCountByKeysAsync(IEnumerable<string> keys)
        {
            var settings = await _dbSet
                .Where(s => keys.Contains(s.Key))
                .GroupBy(s => s.Key)
                .Select(s => new { Key = s.Key, Count = s.Count() })
                .ToListAsync();

            return settings.ToDictionary(s => s.Key, s => s.Count);
        }
    }

    /// <summary>
    /// 用户隐私设置仓储实现
    /// </summary>
    public class UserPrivacySettingRepository : Repository<UserPrivacySetting>, IUserPrivacySettingRepository
    {
        public UserPrivacySettingRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<UserPrivacySetting?> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId);
        }

        public async Task<Dictionary<string, int>> GetPrivacyStatisticsAsync()
        {
            var settings = await _dbSet.ToListAsync();
            var totalUsers = settings.Count;

            if (totalUsers == 0)
            {
                return new Dictionary<string, int>();
            }

            return new Dictionary<string, int>
            {
                { "TotalUsers", totalUsers },
                { "ProfileVisible", settings.Count(s => s.ProfileVisible) },
                { "ActivityVisible", settings.Count(s => s.ActivityVisible) },
                { "MenstrualDataVisible", settings.Count(s => s.MenstrualDataVisible) },
                { "SkincareDataVisible", settings.Count(s => s.SkincareDataVisible) },
                { "MealDataVisible", settings.Count(s => s.MealDataVisible) },
                { "OutfitDataVisible", settings.Count(s => s.OutfitDataVisible) },
                { "GoalDataVisible", settings.Count(s => s.GoalDataVisible) },
                { "AllowDirectMessage", settings.Count(s => s.AllowDirectMessage) },
                { "AllowFriendRequest", settings.Count(s => s.AllowFriendRequest) },
                { "AllowTagging", settings.Count(s => s.AllowTagging) },
                { "DataSharingEnabled", settings.Count(s => s.DataSharingEnabled) }
            };
        }

        public async Task<bool> UpdatePrivacySettingAsync(Guid userId, Dictionary<string, bool> settings)
        {
            var userSetting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId);
            if (userSetting == null)
            {
                userSetting = new UserPrivacySetting { UserId = userId };
                _dbSet.Add(userSetting);
            }

            if (settings.ContainsKey("ProfileVisible"))
                userSetting.ProfileVisible = settings["ProfileVisible"];

            if (settings.ContainsKey("ActivityVisible"))
                userSetting.ActivityVisible = settings["ActivityVisible"];

            if (settings.ContainsKey("MenstrualDataVisible"))
                userSetting.MenstrualDataVisible = settings["MenstrualDataVisible"];

            if (settings.ContainsKey("SkincareDataVisible"))
                userSetting.SkincareDataVisible = settings["SkincareDataVisible"];

            if (settings.ContainsKey("MealDataVisible"))
                userSetting.MealDataVisible = settings["MealDataVisible"];

            if (settings.ContainsKey("OutfitDataVisible"))
                userSetting.OutfitDataVisible = settings["OutfitDataVisible"];

            if (settings.ContainsKey("GoalDataVisible"))
                userSetting.GoalDataVisible = settings["GoalDataVisible"];

            if (settings.ContainsKey("AllowDirectMessage"))
                userSetting.AllowDirectMessage = settings["AllowDirectMessage"];

            if (settings.ContainsKey("AllowFriendRequest"))
                userSetting.AllowFriendRequest = settings["AllowFriendRequest"];

            if (settings.ContainsKey("AllowTagging"))
                userSetting.AllowTagging = settings["AllowTagging"];

            if (settings.ContainsKey("DataSharingEnabled"))
                userSetting.DataSharingEnabled = settings["DataSharingEnabled"];

            userSetting.UpdatedAt = DateTime.UtcNow;
            await _context.SaveChangesAsync();
            return true;
        }
    }

    /// <summary>
    /// 用户主题设置仓储实现
    /// </summary>
    public class UserThemeSettingRepository : Repository<UserThemeSetting>, IUserThemeSettingRepository
    {
        public UserThemeSettingRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<UserThemeSetting?> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId);
        }

        public async Task<Dictionary<string, int>> GetThemeStatisticsAsync()
        {
            var settings = await _dbSet.ToListAsync();
            var totalUsers = settings.Count;

            if (totalUsers == 0)
            {
                return new Dictionary<string, int>();
            }

            return new Dictionary<string, int>
            {
                { "TotalUsers", totalUsers },
                { "LightTheme", settings.Count(s => s.Theme == "light") },
                { "DarkTheme", settings.Count(s => s.Theme == "dark") },
                { "AutoTheme", settings.Count(s => s.Theme == "auto") },
                { "CustomTheme", settings.Count(s => s.Theme == "custom") },
                { "LargeFont", settings.Count(s => s.FontSize == "large") },
                { "MediumFont", settings.Count(s => s.FontSize == "medium") },
                { "SmallFont", settings.Count(s => s.FontSize == "small") },
                { "HighContrast", settings.Count(s => s.HighContrast) },
                { "ReducedMotion", settings.Count(s => s.ReducedMotion) }
            };
        }

        public async Task<bool> UpdateThemeSettingAsync(Guid userId, Dictionary<string, string> settings)
        {
            var userSetting = await _dbSet.FirstOrDefaultAsync(s => s.UserId == userId);
            if (userSetting == null)
            {
                userSetting = new UserThemeSetting { UserId = userId };
                _dbSet.Add(userSetting);
            }

            if (settings.ContainsKey("Theme"))
                userSetting.Theme = settings["Theme"];

            if (settings.ContainsKey("PrimaryColor"))
                userSetting.PrimaryColor = settings["PrimaryColor"];

            if (settings.ContainsKey("SecondaryColor"))
                userSetting.SecondaryColor = settings["SecondaryColor"];

            if (settings.ContainsKey("BackgroundColor"))
                userSetting.BackgroundColor = settings["BackgroundColor"];

            if (settings.ContainsKey("TextColor"))
                userSetting.TextColor = settings["TextColor"];

            if (settings.ContainsKey("FontSize"))
                userSetting.FontSize = settings["FontSize"];

            if (settings.ContainsKey("FontFamily"))
                userSetting.FontFamily = settings["FontFamily"];

            if (settings.ContainsKey("HighContrast"))
                userSetting.HighContrast = bool.Parse(settings["HighContrast"]);

            if (settings.ContainsKey("ReducedMotion"))
                userSetting.ReducedMotion = bool.Parse(settings["ReducedMotion"]);

            userSetting.UpdatedAt = DateTime.UtcNow;
            await _context.SaveChangesAsync();
            return true;
        }
    }

    /// <summary>
    /// 系统日志仓储实现
    /// </summary>
    public class SystemLogRepository : Repository<SystemLog>, ISystemLogRepository
    {
        public SystemLogRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<SystemLog>> GetByLevelAsync(string level)
        {
            return await _dbSet.Where(l => l.Level == level).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByCategoryAsync(string category)
        {
            return await _dbSet.Where(l => l.Category == category).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(l => l.UserId == userId).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Where(l => l.CreatedAt >= startDate && l.CreatedAt <= endDate)
                .OrderByDescending(l => l.CreatedAt)
                .ToListAsync();
        }

        public async Task<Dictionary<string, int>> GetLogCountByLevelAsync()
        {
            var logs = await _dbSet
                .GroupBy(l => l.Level)
                .Select(l => new { Level = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Level, l => l.Count);
        }

        public async Task<Dictionary<string, int>> GetLogCountByCategoryAsync()
        {
            var logs = await _dbSet
                .GroupBy(l => l.Category)
                .Select(l => new { Category = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Category, l => l.Count);
        }

        public async Task<Dictionary<string, int>> GetLogCountByDateAsync(DateTime date)
        {
            var startDate = date.Date;
            var endDate = startDate.AddDays(1);

            var logs = await _dbSet
                .Where(l => l.CreatedAt >= startDate && l.CreatedAt < endDate)
                .GroupBy(l => l.Level)
                .Select(l => new { Level = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Level, l => l.Count);
        }

        public async Task<IEnumerable<SystemLog>> GetErrorLogsAsync(int count = 100)
        {
            return await _dbSet
                .Where(l => l.Level == "error")
                .OrderByDescending(l => l.CreatedAt)
                .Take(count)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemLog>> GetRecentLogsAsync(int count = 100)
        {
            return await _dbSet
                .OrderByDescending(l => l.CreatedAt)
                .Take(count)
                .ToListAsync();
        }

        public async Task<bool> ClearOldLogsAsync(DateTime beforeDate)
        {
            var oldLogs = await _dbSet.Where(l => l.CreatedAt < beforeDate).ToListAsync();
            if (oldLogs.Any())
            {
                _dbSet.RemoveRange(oldLogs);
                await _context.SaveChangesAsync();
                return true;
            }

            return false;
        }
    }

    /// <summary>
    /// 用户操作日志仓储实现
    /// </summary>
    public class UserActionLogRepository : Repository<UserActionLog>, IUserActionLogRepository
    {
        public UserActionLogRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<IEnumerable<UserActionLog>> GetByUserIdAsync(Guid userId)
        {
            return await _dbSet.Where(l => l.UserId == userId).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<UserActionLog>> GetByActionAsync(string action)
        {
            return await _dbSet.Where(l => l.Action == action).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<UserActionLog>> GetByModuleAsync(string module)
        {
            return await _dbSet.Where(l => l.Module == module).OrderByDescending(l => l.CreatedAt).ToListAsync();
        }

        public async Task<IEnumerable<UserActionLog>> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Where(l => l.CreatedAt >= startDate && l.CreatedAt <= endDate)
                .OrderByDescending(l => l.CreatedAt)
                .ToListAsync();
        }

        public async Task<Dictionary<string, int>> GetActionCountByUsersAsync(IEnumerable<Guid> userIds)
        {
            var logs = await _dbSet
                .Where(l => userIds.Contains(l.UserId))
                .GroupBy(l => l.UserId)
                .Select(l => new { UserId = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.UserId.ToString(), l => l.Count);
        }

        public async Task<Dictionary<string, int>> GetActionCountByActionsAsync(IEnumerable<string> actions)
        {
            var logs = await _dbSet
                .Where(l => actions.Contains(l.Action))
                .GroupBy(l => l.Action)
                .Select(l => new { Action = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Action, l => l.Count);
        }

        public async Task<Dictionary<string, int>> GetActionCountByModulesAsync(IEnumerable<string> modules)
        {
            var logs = await _dbSet
                .Where(l => modules.Contains(l.Module))
                .GroupBy(l => l.Module)
                .Select(l => new { Module = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Module, l => l.Count);
        }

        public async Task<Dictionary<string, int>> GetDailyActionCountAsync(DateTime date)
        {
            var startDate = date.Date;
            var endDate = startDate.AddDays(1);

            var logs = await _dbSet
                .Where(l => l.CreatedAt >= startDate && l.CreatedAt < endDate)
                .GroupBy(l => l.Action)
                .Select(l => new { Action = l.Key, Count = l.Count() })
                .ToListAsync();

            return logs.ToDictionary(l => l.Action, l => l.Count);
        }

        public async Task<bool> ClearOldLogsAsync(DateTime beforeDate)
        {
            var oldLogs = await _dbSet.Where(l => l.CreatedAt < beforeDate).ToListAsync();
            if (oldLogs.Any())
            {
                _dbSet.RemoveRange(oldLogs);
                await _context.SaveChangesAsync();
                return true;
            }

            return false;
        }
    }

    /// <summary>
    /// 系统版本仓储实现
    /// </summary>
    public class SystemVersionRepository : Repository<SystemVersion>, ISystemVersionRepository
    {
        public SystemVersionRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<SystemVersion?> GetLatestVersionAsync()
        {
            return await _dbSet.OrderByDescending(v => v.ReleaseDate).FirstOrDefaultAsync();
        }

        public async Task<SystemVersion?> GetByVersionAsync(string version)
        {
            return await _dbSet.FirstOrDefaultAsync(v => v.Version == version);
        }

        public async Task<IEnumerable<SystemVersion>> GetAllVersionsAsync()
        {
            return await _dbSet.OrderByDescending(v => v.ReleaseDate).ToListAsync();
        }

        public async Task<IEnumerable<SystemVersion>> GetVersionsByPlatformAsync(string platform)
        {
            return await _dbSet.Where(v => v.Platform == platform).OrderByDescending(v => v.ReleaseDate).ToListAsync();
        }

        public async Task<bool> IsVersionExistsAsync(string version)
        {
            return await _dbSet.AnyAsync(v => v.Version == version);
        }

        public async Task<Dictionary<string, int>> GetVersionCountByPlatformAsync()
        {
            var versions = await _dbSet
                .GroupBy(v => v.Platform)
                .Select(v => new { Platform = v.Key, Count = v.Count() })
                .ToListAsync();

            return versions.ToDictionary(v => v.Platform, v => v.Count);
        }

        public async Task<Dictionary<string, int>> GetVersionCountByYearAsync()
        {
            var versions = await _dbSet.ToListAsync();
            var result = new Dictionary<string, int>();

            var yearGroups = versions.GroupBy(v => v.ReleaseDate.Year);
            foreach (var group in yearGroups)
            {
                result[group.Key.ToString()] = group.Count();
            }

            return result;
        }
    }

    /// <summary>
    /// 系统维护记录仓储实现
    /// </summary>
    public class SystemMaintenanceRepository : Repository<SystemMaintenance>, ISystemMaintenanceRepository
    {
        public SystemMaintenanceRepository(SheLifeDbContext context) : base(context)
        {
        }

        public async Task<SystemMaintenance?> GetLatestMaintenanceAsync()
        {
            return await _dbSet.OrderByDescending(m => m.StartTime).FirstOrDefaultAsync();
        }

        public async Task<SystemMaintenance?> GetActiveMaintenanceAsync()
        {
            var now = DateTime.UtcNow;
            return await _dbSet
                .Where(m => m.StartTime <= now && m.EndTime >= now && m.Status == "active")
                .FirstOrDefaultAsync();
        }

        public async Task<SystemMaintenance?> GetUpcomingMaintenanceAsync()
        {
            var now = DateTime.UtcNow;
            return await _dbSet
                .Where(m => m.StartTime > now && m.Status == "scheduled")
                .OrderBy(m => m.StartTime)
                .FirstOrDefaultAsync();
        }

        public async Task<IEnumerable<SystemMaintenance>> GetAllMaintenancesAsync()
        {
            return await _dbSet.OrderByDescending(m => m.StartTime).ToListAsync();
        }

        public async Task<IEnumerable<SystemMaintenance>> GetMaintenancesByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            return await _dbSet
                .Where(m => m.StartTime >= startDate && m.EndTime <= endDate)
                .OrderByDescending(m => m.StartTime)
                .ToListAsync();
        }

        public async Task<IEnumerable<SystemMaintenance>> GetPastMaintenancesAsync()
        {
            var now = DateTime.UtcNow;
            return await _dbSet
                .Where(m => m.EndTime < now)
                .OrderByDescending(m => m.StartTime)
                .ToListAsync();
        }

        public async Task<Dictionary<string, int>> GetMaintenanceCountByStatusAsync()
        {
            var maintenances = await _dbSet
                .GroupBy(m => m.Status)
                .Select(m => new { Status = m.Key, Count = m.Count() })
                .ToListAsync();

            return maintenances.ToDictionary(m => m.Status, m => m.Count);
        }

        public async Task<Dictionary<string, int>> GetMaintenanceCountByYearAsync()
        {
            var maintenances = await _dbSet.ToListAsync();
            var result = new Dictionary<string, int>();

            var yearGroups = maintenances.GroupBy(m => m.StartTime.Year);
            foreach (var group in yearGroups)
            {
                result[group.Key.ToString()] = group.Count();
            }

            return result;
        }

        public async Task<bool> UpdateMaintenanceStatusAsync(Guid maintenanceId, string status)
        {
            var maintenance = await _dbSet.FindAsync(maintenanceId);
            if (maintenance != null)
            {
                maintenance.Status = status;
                maintenance.UpdatedAt = DateTime.UtcNow;
                await _context.SaveChangesAsync();
                return true;
            }

            return false;
        }
    }
}